﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SalesSys.BLL.Sales;
using SalesSys.Comm.DAL;
using SalesSys.Comm.Utility;
using SalesSys.DAL.Models;

namespace SalesSys.BLL
{

    public class SequenceApprovalBLL : BaseBLL<SequenceApproval, Guid>
    {
        #region base

        private IRepository<SequenceApprovalItem> _itemRep;

        /// <summary>
        /// 业务相关仓储
        /// </summary>
        private IRepository<SequenceApprovalItem> ItemRep
        {
            get
            {
                return _itemRep ??
                       (_itemRep = RepositoryFactory.GetRepositoryByFactoryUnit<IRepository<SequenceApprovalItem>>());
            }
            set { _itemRep = value; }
        }

        #endregion

        public KeyValuePair<int, IEnumerable<SequenceApproval>> GetData(string title, ApprovalState? state,
            Guid? approverId, int page = 1, int rows = 10)
        {
            var wh = Rep.Entities;
            if (!string.IsNullOrWhiteSpace(title))
            {
                wh = wh.Where(p => p.Title.Contains(title));
            }
            if (state != null)
            {
                wh = wh.Where(p => p.ApprovalState == state.Value);
            }
            if (approverId != null)
            {
                wh = wh.Where(p => p.NowApproverId == approverId);
            }

            var re = wh.OrderByDescending(p => p.CreateTime).Paging(page, rows).ToArray();
            return new KeyValuePair<int, IEnumerable<SequenceApproval>>(wh.Count(), re);
        }

        public KeyValuePair<int, IEnumerable<SequenceApproval>> AdminGetData(string title, ApprovalState? state,
            bool isAll = false, int page = 1, int rows = 10)
        {
            var wh = Rep.Entities.Where(p => p.Title.Contains(title));
            if (state != null)
            {
                wh = wh.Where(p => p.ApprovalState == state.Value);
            }
            if (!isAll)
            {
                wh = wh.Where(p => p.IsAdminHandle == true);
            }

            var re = wh.OrderByDescending(p => p.CreateTime).Paging(page, rows).ToArray();
            return new KeyValuePair<int, IEnumerable<SequenceApproval>>(wh.Count(), re);
        }

        /// <summary>
        /// 编辑节点，
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        /// <remarks>
        /// 检查index是否重复,返回错误
        /// </remarks>
        public IResultState EditItem(SequenceApprovalItem item)
        {
            var old = ItemRep.Entities.Where(p => p.Index == item.Index && p.TypeName == item.TypeName && p.Id != item.Id);
            if (old.Any())
            {
                return ReState.ArgError.Create("序号重复");
            }

            if (item.Approver.Id != null)
            {
                item.Approver = BllFactory.GetBll<EmployeeBLL>().Details(item.Approver.Id);
            }
           var oldItem= ItemRep.Find(item.Id);
           oldItem.Index = item.Index;
           oldItem.Remark = item.Remark;
           oldItem.Approver = item.Approver;
            oldItem.ApproverName = item.Approver.Name;
            oldItem.ExeExpression = item.ExeExpression;
            oldItem.ApproverExpression = item.ApproverExpression;
            ItemRep.Update(oldItem);

            return ReState.Success.Create("修改成功");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        ///    <remarks>
        /// 检查index是否重复,返回错误
        /// </remarks>
        public IResultState AddItem(SequenceApprovalItem item)
        {
            var old = ItemRep.Entities.Where(p => p.Index == item.Index && p.TypeName == item.TypeName);
            if(old.Any())
            {
                return ReState.ArgError.Create("序号重复");
            }

            if(item.Approver.Id != null)
            {
                item.Approver = BllFactory.GetBll<EmployeeBLL>().Details(item.Approver.Id);
            }            

            ItemRep.Insert(item);

            return ReState.Success.Create("新增成功");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="itemId"></param>
        /// <returns></returns>
        /// <remarks>
        /// 检查index是否重复,返回错误
        /// </remarks>
        public IResultState DeleteItem(Guid itemId)
        {
            ItemRep.Delete(itemId);
            return ReState.Success.Create("删除成功");
        }

        #region wf
        /// <summary>
        /// 采购申请
        /// </summary>
        public class PurchasingApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "采购审批";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }

            /// <summary>
            /// 审批完成事件，提供：id,及审批结果
            /// </summary>
            public static event Action<Guid, bool, string> ApprovalEndHandle;

            static PurchasingApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {

                    ApprovalEndHandle(orderId, arg2, arg3);
                }
            }
            /// <summary>
            /// 参数说明
            /// </summary>
            public Tuple<string, Type, string>[] ParamsRemark = new[]
            {
                Tuple.Create("DirectorId", typeof (Guid), "负责人id")
            };

            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="purchaseOrder"></param>
            /// <param name="emp">提交人</param>
            public void Submit(PurchaseOrder purchaseOrder,Employee emp)
            {
                var dic = new Dictionary<string, object>();
                string title = string.Format("申请采购 {0} 商品", purchaseOrder.Provider.Name);
                SetDepOffices(emp, dic);
                Submit(dic,purchaseOrder.Id.ToString(), emp, title);
            }

            static void SetDepOffices(Employee emp, Dictionary<string, object> dic)
            {
                EmployeeBLL bll = new EmployeeBLL();
                var emps = bll.GetDepartmentEmps(emp.Department.Id);
                var dEmp = emps.FirstOrDefault(p => p.Offices == Employee.OfficesConst.Director);
                if (dEmp == null)
                {
                    throw new ArgumentException("无法找到提交人部门负责人");
                }
                dic.Add("DirectorId", dEmp.Id);
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
                if (ApprovalEndHandle != null)
                {
                    OnApprovalEnd += handlers_OnApprovalEnd;
                }
              
               
                base.DoApprovalReEmp(wfId, pass, opinion, employee);

                if (NowHandler.Approval.NowApprover != null)
                {
                    var bll = new BaseBLL<PurchaseOrder, Guid>();
                    var orderId = Guid.Parse(base.NowHandler.Approval.Tag);
                    var ent = bll.Details(orderId);
                    PurchaseOrder.AddPurchaseRecord(null, ent, PurchaseRecordType.ApprovalChange, "待["+NowHandler.Approval.NowApproverName+"]审批");
                }

            }

            protected virtual void handlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != TypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                   // var p = float.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, arg3);
                }
            }

        }

        /// <summary>
        /// 财务退款审批
        /// </summary>
        public class FinanceRefundApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "财务退款审批";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }

            /// <summary>
            /// 审批完成事件，提供：id,及审批结果
            /// </summary>

            public static event Action<Guid, bool, decimal, string> ApprovalEndHandle;

       

            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="account"></param>
            /// <param name="price"></param>
            /// <param name="emp"></param>

            static FinanceRefundApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    var p = decimal.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, p, arg3);
                }
            }


            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="account"></param>
            /// <param name="price"></param>
            /// <param name="emp"></param>
            public void Submit(PaymentInfo paymentInfo, decimal price, Employee emp)
            {
                var dic = new Dictionary<string, object>();
                dic.Add("price", price);
                string title = string.Format("{0},申请退款{1}", paymentInfo.Customer.ShortName, price.ToString("C"));
                Submit(dic, paymentInfo.Id.ToString(), emp, title);
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
                if (ApprovalEndHandle != null)
                {
                    OnApprovalEnd += handlers_OnApprovalEnd;
                }
                base.DoApproval(wfId, pass, opinion, employee);
            }

            protected virtual void handlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != TypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    var p = decimal.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, p, arg3);
                }
            }

        }

        /// <summary>
        /// 报价审批流程
        /// </summary>
        public class PriceConfirmApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "报价审批";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }

            /// <summary>
            /// 审批完成事件，提供：批次id,及审批结果
            /// </summary>
            public static event Action<Guid, bool,string> ApprovalEndHandle;

            static PriceConfirmApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var batchId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    //var p = float.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(batchId, arg2, arg3);
                }
            }


            /// <summary>
            /// 提交到流程，只需要批次中一个记录即可，注意提交批次必须为同一供应商
            /// </summary>
            public void Submit(PriceConfirmData firstInfo)
            {
                var dic = new Dictionary<string, object>();

                EmployeeBLL empBll = new EmployeeBLL();
                var emp=empBll.Details(firstInfo.CreaterId);
                ProviderBLL prvBll = new ProviderBLL();
               var prv= prvBll.Details(firstInfo.ProviderId);
                if (prv.Manager==null)
                {
                    throw new ArgumentException("无法得到供应商区域管理人");
                }
                if (emp==null)
                {
                    throw new ArgumentException("创建人无法找到");
                    
                }
                var mngId=prv.Manager.Id;
                dic.Add("ManagerId",mngId);
                dic.Add("BatchId", firstInfo.BatchId);
                string title = string.Format("{0},对 {1} 的报价申请", emp.Name, prv.Name);

                base.Submit(dic, firstInfo.BatchId.ToString(), emp, title);
            }

            ///// <summary>
            ///// 进行审批
            ///// </summary>
            ///// <param name="wfId"></param>
            ///// <param name="pass"></param>
            ///// <param name="opinion"></param>
            ///// <param name="employee"></param>
            //public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            //{
            //    if (ApprovalEndHandle != null)
            //    {
            //        OnApprovalEnd += handlers_OnApprovalEnd;
            //    }
            //    base.DoApproval(wfId, pass, opinion, employee);
            //}

            //protected virtual void handlers_OnApprovalEnd(SequenceApproval arg1, bool arg2)
            //{
            //    if (arg1.TypeName != TypeName)
            //        return;
            //    var orderId = Guid.Parse(arg1.Tag);
            //    if (ApprovalEndHandle != null)
            //    {
            //        var p = float.Parse(arg1.GetParams()["price"] + "");
            //        ApprovalEndHandle(orderId, arg2, p);
            //    }
            //}

        }

        /// <summary>
        /// 议价审批流程
        /// </summary>
        public class BargainingApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "议价审批";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }

            /// <summary>
            /// 审批完成事件，提供：订单id,及审批结果
            /// </summary>
            public static event Action<Guid, bool, decimal,string> ApprovalEndHandle;

            static BargainingApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    var p = decimal.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, p, arg3);
                }
            }

            
            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="order"></param>
            /// <param name="price"></param>
            public void Submit(Order order, decimal price)
            {
                var dic = new Dictionary<string, object>();
                if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                    throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                dic.Add("SupplierManagerId", order.Provider.Manager.Id);
                dic.Add("price", price);
                dic.Add("SupplierMainFieldManId", order.Provider.MainFieldMan.Id);
                dic.Add("OrderId", order.Id);
                string title = string.Format("{0},申请{1}/t优惠,共{2}t", order.Customer.ShortName, price, order.Weight);

                Submit(dic, order.Id.ToString(), order.Creater, title);
            }
           
            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
                if (ApprovalEndHandle != null)
                {
                    OnApprovalEnd += handlers_OnApprovalEnd;
                }
                base.DoApproval(wfId, pass, opinion, employee);
                if (NowHandler.Approval.NowApprover != null)
                {
                    var bll = new OrderBLL();
                    var orderId = Guid.Parse(base.NowHandler.Approval.Tag);
                    var ent = bll.Details(orderId);
                  
                    var str = string.Format("[{0}]:待[{1}]审批", TypeName, NowHandler.Approval.NowApproverName);
                    OrderBLL.SetOrderChangeRecord(ent, DiscountType.Msg, null, 0, str);
                }
            }

            protected virtual void handlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != TypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    var p = decimal.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, p, arg3);
                }
            }

        }

        /// <summary>
        /// 锁价审批流程，订单锁价审批
        /// </summary>
        public class LockPriceApproval : ContextApprovalBase
        {
            public new const string ApprovalTypeName = "锁价审批";
            /// <summary>
            /// 审批完成事件，提供：订单id,及审批结果
            /// </summary>
            public static event Action<Guid, bool, string> ApprovalEndHandle;

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }
            static LockPriceApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    //var p = float.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, arg3);
                }
            }

            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="order"></param>
            public void Submit(Order order)
            {
                var dic = new Dictionary<string, object>();
                if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                    throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                dic.Add("SupplierManagerId", order.Provider.Manager.Id);
                dic.Add("SupplierMainFieldManId", order.Provider.MainFieldMan.Id);
                dic.Add("OrderId", order.Id);
                string title = string.Format("{0},申请锁价审批,共{1}t", order.Customer.ShortName, order.Weight);
                Submit(dic, order.Id.ToString(), order.Creater, title);
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
 
                base.DoApproval(wfId, pass, opinion, employee);
                if (NowHandler.Approval.NowApprover != null)
                {
                    var bll = new OrderBLL();
                    var orderId = Guid.Parse(base.NowHandler.Approval.Tag);
                    var ent = bll.Details(orderId);
                    var str = string.Format("[{0}]:待[{1}]审批", TypeName, NowHandler.Approval.NowApproverName);
                    OrderBLL.SetOrderChangeRecord(ent, DiscountType.Msg, null, 0, str);
                }
            }


            //protected void handlers_OnApprovalEnd(SequenceApproval arg1, bool arg2)
            //{
            //    if (arg1.TypeName != TypeName)
            //        return;
            //    var orderId = Guid.Parse(arg1.Tag);
            //    if (ApprovalEndHandle != null)
            //    {
            //        ApprovalEndHandle(orderId, arg2);
            //    }
            //}
        }
        /// <summary>
        /// 锁价单审批
        /// </summary>
        public class LockPriceOrderApproval : ContextApprovalBase
        {
            public new const string ApprovalTypeName = "锁价单审批";
            /// <summary>
            /// 审批完成事件，提供：订单id,及审批结果
            /// </summary>
            public static event Action<Guid, bool, string> ApprovalEndHandle;

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }
            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="order"></param>
            public void Submit(LockOrder order)
            {
                var dic = new Dictionary<string, object>();
                if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                    throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                dic.Add("SupplierManagerId", order.Provider.Manager.Id);
                dic.Add("SupplierMainFieldManId", order.Provider.MainFieldMan.Id);
                dic.Add("OrderId", order.Id);
                string title = string.Format("{0},申请[{1}]锁价单审批,共[{2}]元", order.Customer.ShortName, order.OrderType.GetDescInfo(), order.Total);
                Submit(dic, order.Id.ToString(), order.Creater, title);
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
                base.DoApproval(wfId, pass, opinion, employee);
            }


            static LockPriceOrderApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    //var p = float.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, arg3);
                }
            }
        }

        /// <summary>
        /// 取消计划单
        /// </summary>
        public class CancelOrderApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "取消计划单审批";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }
            public static event Action<Guid, bool,string> ApprovalEndHandle;

            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="order"></param>
            public void Submit(Order order)
            {
                var dic = new Dictionary<string, object>();
                if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                    throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                dic.Add("SupplierManagerId", order.Provider.Manager.Id);
                dic.Add("SupplierMainFieldManId", order.Provider.MainFieldMan.Id);
                dic.Add("OrderId", order.Id);
                Submit(dic, order.Id.ToString(), order.Creater);
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
                base.DoApproval(wfId, pass, opinion, employee);
            }


            static CancelOrderApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    //var p = float.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, arg3);
                }
            }
        }
        /// <summary>
        /// 订单退货
        /// </summary>
        public class OrderReturnApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "订单退货";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }
            public static event Action<Guid, bool, string> ApprovalEndHandle;

            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="order"></param>
            public void Submit(Order order)
            {
                var dic = new Dictionary<string, object>();
                if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                    throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                dic.Add("SupplierManagerId", order.Provider.Manager.Id);
                dic.Add("SupplierMainFieldManId", order.Provider.MainFieldMan.Id);
                dic.Add("OrderId", order.Id);
                Submit(dic, order.Id.ToString(), order.Creater, "订单退货");
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {

                base.DoApproval(wfId, pass, opinion, employee);
            }


            static OrderReturnApproval()
            {
                ApprovalHandlers.OnApprovalEnd += ApprovalHandlers_OnApprovalEnd;
            }

            static void ApprovalHandlers_OnApprovalEnd(SequenceApproval arg1, bool arg2, string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                if (ApprovalEndHandle != null)
                {
                    //var p = float.Parse(arg1.GetParams()["price"] + "");
                    ApprovalEndHandle(orderId, arg2, arg3);
                }
            }
        }
        /// <summary>
        /// 订单退款
        /// </summary>
        public class OrderRefundApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "订单退款";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }
            public static event Action<Guid, bool,decimal,string> ApprovalEndHandle;

            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="order"></param>
            public Guid Submit(Order order, decimal money)
            {
                var dic = new Dictionary<string, object>();
                if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                    throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                dic.Add("SupplierManagerId", order.Provider.Manager.Id);
                dic.Add("SupplierMainFieldManId", order.Provider.MainFieldMan.Id);
                dic.Add("OrderId", order.Id);
                dic.Add("money", money);
                return Submit(dic, order.Id.ToString(), order.Creater);
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
                if (ApprovalEndHandle != null)
                {
                    OnApprovalEnd += handlers_OnApprovalEnd;
                }
                base.DoApproval(wfId, pass, opinion, employee);
            }

            static OrderRefundApproval()
            {
                ApprovalHandlers.OnApprovalEnd += handlers_OnApprovalEnd;
            }



            private static void handlers_OnApprovalEnd(SequenceApproval arg1, bool arg2,string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                var paramDic = arg1.GetParams();
                var money = (decimal)paramDic["money"];
                if (ApprovalEndHandle != null)
                {
                    ApprovalEndHandle(orderId, arg2, money, arg3);
                }
            }


        }
        /// <summary>
        /// 锁价单退款
        /// </summary>
        public class LockOrderRefundApproval : ContextApprovalBase
        {
            public const string ApprovalTypeName = "锁价单退款";

            public override string TypeName
            {
                get { return ApprovalTypeName; }
            }

            public static event Action<Guid, bool, decimal,string> ApprovalEndHandle;

            /// <summary>
            /// 提交到流程
            /// </summary>
            /// <param name="order"></param>

            public void Submit(LockOrder order, decimal money)
            {
                var dic = new Dictionary<string, object>();
                if (order.Provider.Manager == null || order.Provider.MainFieldMan == null)
                    throw new Exception("供应商驻厂专员或区域经理未配置，请联系管理员。");
                dic.Add("SupplierManagerId", order.Provider.Manager.Id);
                dic.Add("SupplierMainFieldManId", order.Provider.MainFieldMan.Id);
                dic.Add("OrderId", order.Id);
                dic.Add("money", money);
                Submit(dic, order.Id.ToString(), order.Creater,"锁价单退款："+money.ToString("C"));
            }

            /// <summary>
            /// 进行审批
            /// </summary>
            /// <param name="wfId"></param>
            /// <param name="pass"></param>
            /// <param name="opinion"></param>
            /// <param name="employee"></param>
            public override void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
            {
                if (ApprovalEndHandle != null)
                {
                    OnApprovalEnd += handlers_OnApprovalEnd;
                }
                base.DoApproval(wfId, pass, opinion, employee);
            }

            static LockOrderRefundApproval()
            {
                ApprovalHandlers.OnApprovalEnd += handlers_OnApprovalEnd;
            }



            private static void handlers_OnApprovalEnd(SequenceApproval arg1, bool arg2,string arg3)
            {
                if (arg1.TypeName != ApprovalTypeName)
                    return;
                var orderId = Guid.Parse(arg1.Tag);
                var paramDic = arg1.GetParams();
                var money = Convert.ToDecimal (paramDic["money"]);
                if (ApprovalEndHandle != null)
                {
                    ApprovalEndHandle(orderId, arg2, money, arg3);
                }
            }

        }
        #endregion
    }

    #region helper

   
    public interface IApprovalWork
    {
        string TypeName { get; }
        IList<SequenceApprovalItem> Items { get; }
       Guid  Submit(IDictionary<string, object> param, string tag,Employee creater,string title);
       void  DoApproval(Guid wfId, bool pass, string opinion, Employee approval);
        /// <summary>
        /// 审批完成事件，提供：订单id,及审批结果
        /// </summary>
        //event Action<SequenceApproval, bool> OnApprovalEnd;
    }
    [InheritedExport(typeof(IApprovalWork))]
    public abstract class ContextApprovalBase : IApprovalWork
     {
      protected  static void SetDepOfficesParam(Employee emp, Dictionary<string, object> dic, string offices = Employee.OfficesConst.Director)
        {
            EmployeeBLL bll = new EmployeeBLL();
            var emps = bll.GetDepartmentEmps(emp.Department.Id);
            var dEmp = emps.FirstOrDefault(p => p.Offices == offices);
            if (dEmp == null)
            {
                throw new ArgumentException("无法找到提交人部门负责人");
            }
            dic.Add("DirectorId", dEmp.Id);
        }
         static  IEnumerable<IApprovalWork> works;

         public static IEnumerable<IApprovalWork> GetApprovalWorks()
         {
             if (works == null)
             {
                 CompositionContainer container =
                     new CompositionContainer(new AssemblyCatalog(typeof (ContextApprovalBase).Assembly));
                 works = container.GetExportedValues<IApprovalWork>();
             }
             return works;


         }

         #region base
        private IRepository<SequenceApprovalItem> _itemRep;

        /// <summary>
        /// 业务相关仓储
        /// </summary>
        private IRepository<SequenceApprovalItem> ItemRep
        {
            get { return _itemRep ?? (_itemRep = RepositoryFactory.GetRepositoryByFactoryUnit<IRepository<SequenceApprovalItem>>()); }
            set { _itemRep = value; }
        }
#endregion
        public abstract string TypeName { get; }
        public   IList<SequenceApprovalItem> Items {
            get { 
                var tmp=ItemRep.Entities.Where(p => p.TypeName == TypeName).OrderBy(p=>p.Index).ToArray();
                return items = tmp;
            }
        }

        private IList<SequenceApprovalItem> items;
        /// <summary>
        /// 审批完成事件，提供：订单id,及审批结果
        /// </summary>
        public static event Action<SequenceApproval, bool, string> OnApprovalEnd;

        private ApprovalHandlers handler;

        protected ApprovalHandlers NowHandler
        {
            get
            {
                return handler;
            }
        }

        /// <summary>
        /// 提交到流程
        /// </summary>
        /// <param name="order"></param>
        /// <param name="price"></param>
        public Guid Submit(IDictionary<string, object> param, string tag,Employee creater,string title=null)
        {
            return new ApprovalHandlers().Submit(TypeName, creater, param, tag, title);
        }
        /// <summary>
        /// 进行审批
        /// </summary>
        /// <param name="wfId"></param>
        /// <param name="pass"></param>
        /// <param name="opinion"></param>
        /// <param name="employee"></param>
        public virtual void DoApproval(Guid wfId, bool pass, string opinion, Employee employee)
        {
            handler = new ApprovalHandlers(wfId);
            if (OnApprovalEnd != null)
            {
                ApprovalHandlers.OnApprovalEnd += OnApprovalEnd; // handlers_OnApprovalEnd;
            }

            handler.DoApproval(pass, opinion, employee);
           
        }
        public virtual IEmployee DoApprovalReEmp(Guid wfId, bool pass, string opinion, Employee employee)
        {
            handler = new ApprovalHandlers(wfId);
            if (OnApprovalEnd != null)
            {
                ApprovalHandlers.OnApprovalEnd += OnApprovalEnd; // handlers_OnApprovalEnd;
            }

            handler.DoApproval(pass, opinion, employee);
            return handler.Approval.NowApprover;
        }

    
     }
    public sealed class ApprovalHandlers : BaseBLL<SequenceApproval, Guid>
    {
        private IRepository<SequenceApprovalItem> _itemRep;

        /// <summary>
        /// 业务相关仓储
        /// </summary>
        private IRepository<SequenceApprovalItem> ItemRep
        {
            get { return _itemRep ?? (_itemRep = RepositoryFactory.GetRepositoryByFactoryUnit<IRepository<SequenceApprovalItem>>()); }
            set { _itemRep = value; }
        }
        public static event Action<SequenceApproval, bool, string> OnApprovalEnd;
        public SequenceApproval Approval { get; private set; }
        public IList<SequenceApprovalItem> Items { get; private set; }
        public ApprovalHandlers(Guid? approvalId = null)
        {
            if (approvalId != null)
            {
                Approval = Rep.Find(approvalId);

                Items = ItemRep.Entities.Where(p => p.TypeName == Approval.TypeName).OrderBy(p=>p.Index).ToArray();
            }
        }

        /// <summary>
        /// 提交到指定工作流
        /// </summary>
        /// <param name="typeName"></param>
        /// <param name="param"></param>
        /// <param name="tag"></param>
        public Guid  Submit(string typeName,Employee creater, IDictionary<string, object> param = null, string tag = null,string title=null)
        {
            try
            {
                var appl = new SequenceApproval();
                appl.Creater = creater;
                appl.CreateTime = DateTime.Now;
                appl.TypeName = typeName;
                appl.ApprovalState = ApprovalState.Pending;
                appl.Title = title;
                var tyepItems = ItemRep.Entities.Where(p => p.TypeName == typeName).OrderBy(p=>p.Index).ToArray();
                if (tyepItems.Length < 1)
                {
                    throw new ArgumentException("流程项为空");
                }
                appl.SetItems(tyepItems);
                Items = tyepItems;
                if (param != null)
                {
                    appl.Params = SimpleJson.Serializer(param);
                }
                appl.Tag = tag;
                Approval = appl;
                GoNext();
                Create(appl);
                return appl.Id;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private bool? Discretion(SequenceApprovalItem item)
        {
            if (item.ExeExpression == null)
            {
                return true;
            }
            var re = ExpressionHandle(item.ExeExpression, Approval.GetParams()) as bool?;
            return re;
        }

        private object ExpressionHandle(string expression, IDictionary<string, object> param = null)
        {
            return hlib.Code.ExpressionEval.Expression<object>(expression, param);
        }

        public void DoApproval(bool pass, string opinion, Employee employee)
        {
            var approval = Approval;
            approval.NowRemark = opinion;
            if (approval.IsAdminHandle)
            {
                AdminDoApproval(pass, opinion, employee);
                return;
            }
            if (Approval.NowApprover.Id != employee.Id)
            {
                throw new ArgumentException("审批人与流程不符");
            }
            if (pass)
            {
                //写入审批记录
                NotesApproval(true, opinion);
                //获取下个
                try
                {
                    var nItem = GoNext();

                }
                catch (Exception ex)
                {
                    AdminHandle(ex);
                }
            }
            else
            {
                EndApproval(false, opinion);
                SendDisagreeMsg(approval);
       
            }
            Rep.Update(Approval);
            if (Approval.ApprovalState == ApprovalState.Agree || Approval.ApprovalState == ApprovalState.Disagree)
            {
                if (OnApprovalEnd != null) OnApprovalEnd(Approval, pass, opinion);
            }
        }

        private void SendDisagreeMsg(SequenceApproval seq)
        {
            if (seq.Creater == null)
            {
                return;
            }
            var nb = new NoticeInfoBLL();
            var str = string.Format("{0:M/d HH:mm} [审批驳回]{1}: {2}", DateTime.Now, seq.TypeName, seq.Title);
            nb.SendMsg(str, seq.Creater.Id, null);


        }

        private void AdminDoApproval(bool pass, string opinion, Employee employee)
        {
            if (employee.Id != new SysConfigBLL().ApprovalAdmin())
            {
                throw new ArgumentException("审批人与流程不符");
            }

            NotesApproval(pass, opinion, false, employee);
            EndApproval(pass);
        }

        public void NotesApproval(bool pass, string opinion = null, bool isEnd = false, Employee employee = null)
        {
            var record = new ApprovalRecord();
            if (isEnd)
            {
                //终结点无审批人与节点
            }
            else if (Approval.IsAdminHandle)
            {
                record.Approver = employee;
            }
            else
            {
                record.ApprovalItem = Approval.NowItem;
                record.Approver = Approval.NowApprover;
            }
            record.CreateTime = DateTime.Now;
            record.IsAgree = pass;
            record.Opinion = opinion;
            if (isEnd)
            {
                record.Remarks = string.Format("{0}审批 {1}", Approval.TypeName, pass ? "通过" : "驳回");                
            }
            else
            {
                record.Remarks = string.Format("{0} 审批 {1}", record.Approver.Name, pass ? "通过" : "驳回");
            }
            
            Approval.Records.Add(record);

        }

        public SequenceApprovalItem GoNext()
        {
            var approval = Approval;
            //var Items = approval.GetItems();
            SequenceApprovalItem item = null;
            var isSelected = false;

            //第一次，nowItem=null
            //中间,id
            //最后,i+1=count;
            for (int i = 0; i < Items.Count; i++)
            {
                if (approval.NowItem == null)
                {
                    isSelected = true;
                    item = Items[0];
                    break;
                }
                else if (Items[i].Id == approval.NowItem.Id)
                {
                    isSelected = true;
                    //中间
                    if (i + 1 < Items.Count)
                    {
                        item = Items[i + 1];
                        break;
                    }
                    else
                    {//最后一项
                        item = null;
                        break;
                    }
                }
            }
            if (!isSelected)
            {
                AdminHandle(new ArgumentException("无法找到的项:" + approval.NowItem.Id));
                return null;
            }
            if (item == null)
            {
                EndApproval(true);
                return null;
            }
            approval.NowItem = item;
            approval.NowApprover = GetApprover(item);
            approval.NowApproverName = approval.NowApprover.Name;
            var re = Discretion(item);

            switch (re)
            {
                case true:
                    SendMsg(approval);
                    return item;
                case false:
                    return GoNext();
                default:
                    //错误处理
                    AdminHandle(new ArgumentException("条件表达式错误:" + item.ExeExpression));
                    break;
            }
            return null;
        }

        private void SendMsg(SequenceApproval seq)
        {
            var nb = new NoticeInfoBLL();
            var str = string.Format("{0:M/d HH:mm} [{1}] {2}", DateTime.Now, seq.TypeName, seq.Title);
                nb.SendMsg(str, seq.NowApprover.Id, null);
        }

        public Employee GetApprover(SequenceApprovalItem item)
        {
            if (string.IsNullOrWhiteSpace(item.ApproverExpression))
            {
                return item.Approver;
            }
            var re = ExpressionHandle(item.ApproverExpression, Approval.GetParams());
            var id = Guid.Parse(re.ToString());
            var emp = new EmployeeBLL().Details(id);
            return emp;
        }

        void EndApproval(bool pass, string opinion = null)
        {
            var approval = Approval;
            //设置审批结果
            approval.ApprovalState = pass ? ApprovalState.Agree : ApprovalState.Disagree;
            NotesApproval(pass, opinion, true);

        }

        void AdminHandle(Exception ex)
        {
            Approval.NowRemark = ex.ToString();
            Approval.IsAdminHandle = true;
            Approval.NowIsRedirect = true;
        }
    }
    #endregion
}
